package com.singlemusic.dao;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.stereotype.Repository;


@Repository(value="baseDao")
public class BaseDaoImpl<T> implements BaseDao<T> {
	
	@Resource(name="sessionFactory")
	private SessionFactory sessionFactory;
	@Override
	public boolean add(T t) {
		Session session = null;
		Transaction tx = null;
		boolean result = false;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			session.save(t);
			tx.commit();
			result = true;
		} catch (Exception e) {
			// TODO: handle exception
			result = false;
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return result;
	}

	@Override
	public boolean delete(T t) {
		// TODO Auto-generated method stub
		Session session = null;
		Transaction tx = null;
		boolean result = false;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			session.delete(t);
			tx.commit();
			result = true;
		} catch (Exception e) {
			// TODO: handle exception
			result = false;
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findByID(Class<T> c, Serializable id) {
		// TODO Auto-generated method stub
		Session session = null;
		Transaction tx = null;
		T t = null;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			t = (T)session.get(c, id);
			tx.commit();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return t;
	}

	@Override
	public boolean update(T t) {
		Session session = null;
		Transaction tx = null;
		boolean result = false;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			session.update(t);
			tx.commit();
			result = true;
		} catch (Exception e) {
			result = false;
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return result;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> findAll(Class<T> c) {
		Session session = null;
		Transaction tx = null;
		List<T> list = null;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			Query query = session.createQuery("from "+c.getName());
			list = query.list();
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findByHql(String hql, String[] param) {
		Session session = null;
		Transaction tx = null;
		List<T> list = null;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			Query query = session.createQuery(hql);
			if(param != null && param.length > 0){
				for(int i=0; i<param.length; i++){
					query.setString(i, param[i]);
				}
			}
			list = query.list();
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findBySql(Class<T> c, String sql, String[] param) {
		Session session = null;
		Transaction tx = null;
		List<T> list = null;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			Query query = session.createSQLQuery(sql).addEntity(c);
			if(param != null && param.length > 0){
				for(int i=0; i<param.length; i++){
					query.setString(i, param[i]);
				}
			}
			list = query.list();
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return list;
	}

	
	@SuppressWarnings("unchecked")
	@Override
	public int getResultCount(String hql, String[] param) {
		Session session = null;
		Transaction tx = null;
		int totalRows = 0;
		try {
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			Query query = session.createQuery(hql);
			if(param != null && param.length > 0){
				for(int i=0; i<param.length; i++){
					query.setString(i, param[i]);
				}
			}
			List<T> list = query.list();
			totalRows = list.size();
			tx.commit();
		} catch(Exception e){
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		} finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		
		return totalRows;
	}
	
	@Override
	public boolean merge(T t) {
		Session session = null;
		Transaction tx = null;
		boolean result = false;
		try{
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			session.merge(t);
			tx.commit();
			result = true;
		}catch(Exception e){
			result = false;
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		}finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> findByPage(String hql, String[] param, int page, int row){
		Session session = null;
		Transaction tx = null;
		List<T> list = null;
		try{
			session = sessionFactory.getCurrentSession();
			tx = session.beginTransaction();
			Query query = session.createQuery(hql);
			if(param != null && param.length > 0){
				for(int i=0; i<param.length; i++){
					query.setString(i, param[i]);
				}
			}
			query.setFirstResult((page-1)*row).setMaxResults(row);
			list = query.list();
			tx.commit();
		} catch(Exception e){
			e.printStackTrace();
			if(tx != null){
				tx.rollback();
			}
			throw new RuntimeException(e.getMessage());
		} finally{
			if(session != null && session.isOpen()){
				session.close();
			}
		}
		return list;
	}
}
